package com.sgq.vue.service.resource.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sgq.vue.config.WeatherDaysConstant;
import com.sgq.vue.dao.resource.CityMapper;
import com.sgq.vue.dao.resource.WeatherMapper;
import com.sgq.vue.entity.picture.Picture;
import com.sgq.vue.entity.picture.Tag;
import com.sgq.vue.entity.resource.City;
import com.sgq.vue.entity.resource.JsonMapWeather;
import com.sgq.vue.entity.resource.Weather;
import com.sgq.vue.entity.resource.WeatherApi;
import com.sgq.vue.enums.RequestConditionEnums;
import com.sgq.vue.service.picture.PictureService;
import com.sgq.vue.service.picture.TagService;
import com.sgq.vue.service.resource.JsonMapWeatherService;
import com.sgq.vue.service.resource.WeatherApiService;
import com.sgq.vue.service.resource.WeatherService;
import com.sgq.vue.utils.resource.FieldsUtil;
import com.sgq.vue.utils.resource.RequestUrlBuilder;
import com.sgq.vue.utils.system.MenuTree;
import com.sgq.vue.utils.resource.WeatherUtil;
import com.sgq.vue.vo.query.resource.UserWeatherVo;
import com.sgq.vue.vo.query.resource.WeatherQueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 83778
 * @date: 2023-12-19 18:46
 * @desc:
 */
@Service
public class WeatherServiceImpl extends ServiceImpl<WeatherMapper, Weather> implements WeatherService {

    @Autowired
    private CityMapper cityMapper;

    @Autowired
    private WeatherApiService weatherApiService;

    @Autowired
    private JsonMapWeatherService jsonMapWeatherService;

    @Autowired
    private TagService tagService;

    @Autowired
    private PictureService pictureService;

    @Override
    @Transactional
    @CacheEvict(cacheNames = "weather::user" , key = "'userId:'+ #userId",allEntries = true)
    public boolean saveUserWeather(Long userId,List<Long> cityIds) {
        this.baseMapper.deleteByUserId(userId);
        Integer count = this.baseMapper.saveUserWeather(userId,cityIds);
        return count == cityIds.size() ? true : false;
    }

    @Override
    public List<Weather> findWeatherHistory(WeatherQueryVo weatherQueryVo) {
        List<Long> cityIds = this.baseMapper.selectCityIdsByUserId(weatherQueryVo.getCityId());
        LambdaQueryWrapper<Weather> queryWrapper = new LambdaQueryWrapper<>();
        String city = weatherQueryVo.getCity();
        queryWrapper.in(Weather::getId,cityIds);
        if (!ObjectUtils.isEmpty(city)){
            queryWrapper.like(Weather::getCity,city);
        }
        queryWrapper.orderByAsc(Weather::getId);
        List<Weather> weathers = this.baseMapper.selectList(queryWrapper);
        return weathers;
    }

    @Override
    public boolean removeByUserId(Long userId) {
        this.baseMapper.deleteByUserId(userId);
        return true;
    }

    /**
     * 将查询到的天气记录到数据库并返回（只查询用户已添加的城市天气）
     * @param weatherQueryVo
     * @return
     */
    @Override
    @Cacheable(cacheNames = "weather::user", key = "'userId:'+ #userId")
    public List<Weather> findWeatherOnline(WeatherQueryVo weatherQueryVo,Long userId) {

        //查询要显示天气的城市
        List<Long> cityIds = this.baseMapper.selectCityIdsByUserId(userId);
        //请求线上数据
        List<Weather> weathers = WeatherUtil.getWeatherInfoOnline(cityIds);
        //将缺乏城市名字的城市补充名字和leaderCode并排序
        List<Weather> sortedWeathers = this.completeCityName(weathers);

        //将查询到的天气进行插入数据库
        for (Weather weather : sortedWeathers) {
             this.baseMapper.insert(weather);
        }
        return sortedWeathers;
    }

    /**
     * 用于构建勾选列表，哪些城市已关注，哪些未关注
     * @param userId
     * @param roleIds
     * @return
     */
    @Override
    public UserWeatherVo findUserWeatherTree(Long userId, List<Long> roleIds) {
        //1.查询当前用户已经拥有的城市id
        List<Long> cityIds = this.baseMapper.selectCityIdsByUserId(userId);
        //2.查询当前用户角色所包含的城市详细信息（需要用于树形列表）
        List<City> cities = cityMapper.selectCityListByRoleIds(roleIds);

        List<City> cityTree = MenuTree.makeCityTree(cities, 10000L);
        //3.查询要分配角色的原有城市（被分配角色原本已拥有的城市）

        UserWeatherVo vo = new UserWeatherVo();
        vo.setCityList(cityTree);
        vo.setCheckList(cityIds.toArray());
        return vo;
    }

    /**
     * 多源头获取消息
     * @param weatherQueryVo
     * @param userId
     * @return
     */
    @Override
    @Cacheable(cacheNames = "weather::user", key = "'userId:'+ #userId")
    public List<Weather> findWeatherOnlineByDynamic(WeatherQueryVo weatherQueryVo, Long userId, Integer days) {
        //1.通过userId找到已起用可用的源头
        LambdaQueryWrapper<WeatherApi> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WeatherApi::getBelongs,userId);
        queryWrapper.eq(WeatherApi::getState,1);
        WeatherApi weatherApi = weatherApiService.getOne(queryWrapper);

        //2.查询要展示天气的城市
        List<Long> cityIds = this.baseMapper.selectCityIdsByUserId(userId);
        List<City> cityList = cityMapper.selectBatchIds(cityIds);
        //3.构建请求地址(为哪些城市构建天气请求地址)
        List<Weather> weathers = RequestUrlBuilder.buildCondition(cityList, weatherApi);

        //3.获取数据并整理成weather对象
        Long id = weatherApi.getId();
        //获取映射对象
        JsonMapWeather mapping = jsonMapWeatherService.findMappingByWeatherApiId(id);
        FieldsUtil<JsonMapWeather, Weather> fieldsUtil = new FieldsUtil<>();

        for (int i = 0; i < weathers.size(); i++) {
            //获取getTagType中临时赋值的请求url
            String json = WeatherUtil.simpleRequest(weathers.get(i).getTagType());
            //如果json为空 则不设置天气数据
            if(ObjectUtils.isEmpty(json)){
                continue;
            }
            Weather weather = weathers.get(i);
            //记录cityId
            Long cityId = weather.getCityId();

            List<Weather> list = fieldsUtil.setSameFiledValue(mapping, weather, json, days);
            BeanUtils.copyProperties(list.get(0),weather);
            weather.setCityId(cityId);

           if (days.equals(WeatherDaysConstant.SEVEN_DAYS)){
               //获取7天天气的api
               List<Weather> weatherUrlList = RequestUrlBuilder.buildCondition(Arrays.asList(cityList.get(i)), weatherApiService.getById(13L));
               String sevenDaysJson = WeatherUtil.simpleRequest(weatherUrlList.get(0).getTagType());
               List<Weather> sevenList = fieldsUtil.setSameFiledValue(mapping, weather, sevenDaysJson, WeatherDaysConstant.SEVEN_DAYS);
               weather.getParam().put("SEVEN_DAYS",sevenList);
            }

        }

        List<Weather> sortedWeathers = this.completeCityName(weathers);
        //4.入库并插入到缓存
        for (Weather weather : sortedWeathers) {
             this.baseMapper.insert(weather);
        }
        return sortedWeathers;
    }



    private City getCityNameById(Long id){
        City city = cityMapper.selectById(id);
        return city;
    }

    /**
     *  检查city名字为null的从数据库中获取名字补充
     * @param weatherList
     * @return
     */
    private List<Weather> completeCityName(List<Weather> weatherList){
        System.out.println("weatherList = " + weatherList);
      List<Weather> list = weatherList.stream()
                .sorted(Comparator.comparingLong(Weather::getCityId))
                .collect(Collectors.toList());
        list.forEach(temp -> {
            String cityName = temp.getCity();
            Long cityId = temp.getCityId();
            City city = this.getCityNameById(cityId);
            if(ObjectUtils.isEmpty(cityName)){
                String name = city.getCityZh();
                temp.setCity(name);
            }
            //从数据库中获取天气图片（wea是天气的名称，一般天气名称与天气图片名字一致）
            String wea = temp.getWea();
            //如果是空 直接设置为默认图片
            if(ObjectUtils.isEmpty(wea)){
                //未知天气图片的id 54L
                temp.setWeaImg(pictureService.getById(54L).getUrl());

            }else {
                //1-通过wea名字（天气情况，天气图片被打上了天气标签）找到相关标签id
                LambdaQueryWrapper<Tag> queryWrapper = new LambdaQueryWrapper<>();

                queryWrapper.eq(Tag::getName,wea);

                //找到tag名字与天气情况名字一致的tag
                Tag one = tagService.getOne(queryWrapper);

                //2-再通过标签获取图片
                List<Picture> images = pictureService.findWeatherImgByTagId(one.getId());

                if (images.size() == 0 || images == null){
                    temp.setWeaImg(pictureService.getById(54L).getUrl());
                }else {
                    temp.setWeaImg(images.get(0).getUrl());
                }


            }

            Long leaderCode = city.getLeaderCode();
            String tagType = leaderCode.toString().length() <= 8 ? "danger" : "success";
            temp.setTagType(tagType);
        });

        return list;
    }
}
